#pragma once

#include <string>
#include <vector>
#include <thread>
#include <mutex>
#include <atomic>
#include <cstdint>
#include <chrono>
#include <utility>
#include <unordered_set>

class FtpUploader {
public:
    // ctor: basic (no files)
    FtpUploader(const std::string& user,
                const std::string& pass,
                const std::string& remoteDir,
                int threadCount = 4);

    // ctor: with initial file-pairs (localPath, relativeRemotePath)
    FtpUploader(const std::string& user,
                const std::string& pass,
                const std::string& remoteDir,
                const std::vector<std::pair<std::string,std::string>>& files,
                const std::string& reportFile,
                int threadCount = 4);

    ~FtpUploader();

    // legacy: set list of local files only (will upload under remoteBase root)
    void setFiles(const std::vector<std::string>& files);

    // new: set file pairs (localPath, relativeRemotePath)
    void setFilePairs(const std::vector<std::pair<std::string,std::string>>& filePairs);

    // run the upload task (blocking)
    void run();

private:
    // create an arbitrary remote dir (best-effort). remoteDir should be full ftp url (e.g. ftp://host/Test/ts/sub)
    bool createRemoteDirAt(const std::string& remoteDir);

    // worker that consumes m_filePairs
    void workerThreadFunc();

    // upload one local<->remote pair; returns true on success
    bool uploadSingleFilePair(const std::pair<std::string,std::string>& filePair);

private:
    std::string m_user;
    std::string m_pass;
    std::string m_reportFile;
    // remote base url (example: ftp://host/Test/2025-08-06-20-00)
    std::string m_remoteBase;

    int m_threadCount{1};

    // file pairs: (localPath, relativeRemotePath)
    std::vector<std::pair<std::string,std::string>> m_filePairs;

    // legacy single-list (optional)
    std::vector<std::string> m_files;

    // dispatch index and mutex
    std::mutex m_idxMutex;
    size_t m_nextIndex{0};

    // CSV/console lock
    std::mutex m_csvMutex;

    // totals (64-bit-safe)
    std::atomic<uint64_t> total_local_bytes{0};
    std::atomic<uint64_t> total_uploaded_bytes{0};

    // task timing
    std::chrono::steady_clock::time_point m_startTime;
    std::chrono::steady_clock::time_point m_endTime;

private:
    std::mutex m_dirMutex;
    std::unordered_set<std::string> m_createdDirs;
    std::unordered_set<std::string> m_failedDirs;
};
